#include "aux.h"


/**
 * Creates and opens a Unix FIFO with "name" name
 */
int createFifo(char *name, mode_t mode) {

	mkfifo(name, 0660);
	int fd = open(name, mode);
	return fd;
}

/**
 * Opens FIFO, returns -1 on error
 */
/*int openFifo(char *name, mode_t mode) {
	
	int fd, sleepTime = 0;	
	do {
		fd = open(name, mode);
		if (fd == -1) sleep(1);
		sleepTime++;
	} while (fd == -1 && sleepTime < FIFO_MAX_OPEN_TRIES);
	return fd;
}*/

/**
 * Reads FIFO
 */
void readFifo(int fd, char *str) {
	while(readline(fd, str)) printf("read: %s",str);
	return;
}

/**
 * Loads the user file to a vector
 */
vec* loadUsers(char *filename, unsigned int *lastID) {
        FILE *file;
        char line[BUFFER_MAX];
        

        file = fopen(filename, "r");        
        if (file == NULL) {
                puts("File does not exist."); // TODO log this
        }
        else {
                fscanf(file,"%7u\n", lastID);
        }
        
         *lastID = (file == NULL ? -1 : *lastID);
         vec *users = createVector(*lastID + 1, sizeof(user));
  
         if (file != NULL) {
             int status = 0;
             do {
                 user *NewUser = (user *)malloc(sizeof(user));
                 status = fscanf(file, "%7u %20c %4c %lf\n",
               &NewUser->id,              
               &NewUser->name,
               &NewUser->pin,
               &NewUser->balance);
               if (status != EOF)
                  addElement(users, NewUser);
              }while(status != EOF);
         }
         return users;
}

/**
 * Saves the users to a file
 */
int saveUsers(vec * users, char *filename, unsigned int lastID) {
	FILE *file = fopen(filename, "w");
	
	if (file == NULL)
		return -1;
	
	// Writes the last account number first
	fprintf(file, "%07u\n", lastID);
	
	// Writes the accounts
	size_t i;
	for (i = 0; i < users->elements; ++i) {
	user *NewUser = users->array[i];
	fprintf(file, "%07u %-20s %-4s %10.3lf\n",
		  NewUser->id,
		  NewUser->name,
		  NewUser->pin,
		  NewUser->balance);
	}
	fclose(file);
  	return 0;
}

/**
 * Prints the information about the users
 */
void printUsers(vec * users) {
	puts("Users:");
	int i;
	for (i = 0; i < users->elements; i++) {
		printf("%u %s +%e \n", ((user *)users->array[i])->id, ((user *)users->array[i])->name, ((user *)users->array[i])->balance);
	}
}

/**
 * Adds a user
 */
/*int addUser(vec * users, unsigned int *lastID, char *name, char *pin) {

	*lastID += 1;
	user * newUser = (user *)malloc(sizeof(user));
	newUser->id = *lastID;
	strcpy(newUser->name, name);
	strcpy(newUser->pin, pin);
	newUser->balance = 0;
	
	addElement(users, newUser);
	
	return SUCCESS;
}*/

/**
 * Removes a user
 */
int removeUser(vec * users, unsigned int id) {
	int i;
	for(i=0; i < users->elements; i++) {
		if ( ((user *)users->array[i])->id == id ) {
			removeElement(users, i);			
			return SUCCESS;
		}
	}
	return ERROR;
}


user* getUser(vec * users, unsigned id) {
	int i;
	for(i=0; i < users->elements; i++) {
		if ( ((user *)users->array[i])->id == id ) {
			return ((user *)users->array[i]);
		}
	}
	return NULL;
}

double setBalance(user * _user, double amount) {
	_user->balance = amount;
}


/**
 * Reads a line from the file descriptor
 */
int readline(int fd, char *str) {
    int n;
     do
     {
       n = read(fd,str,1);
       str++;
     }
     while (n>0 && *(str-1) != '\n' && *(str-1) != '\0');
     *str='\0';
     return (n>0);
}

/**
 * Sorts users
 */
void sortUsers(vec *users) {
	qsort(users->array, users->elements, sizeof(user), compareUsers);
}

/**
 * Compares 2 users
 */
int compareUsers(const void *u1, const void *u2) {
	user * user1 = (user *) u1;
	user * user2 = (user *) u2;
	return (user1->id > user2->id);
}

/**
 * Auxiliary function to open a fifo
 */
int Open_Fifo(int pid)
{
	int fd_ans;
	char *str;
	str = (char *) malloc(256*sizeof(char));

	sprintf(str,"%s%d", "ans", pid);

	printf("Open fifo: %s\n", str);
	fd_ans=open(str,O_RDWR);

	return fd_ans;
}

/**
 * Auxiliary function to empty stdin
 */
void CleanStdin(void) {
  char c;
  while (((c = getchar()) != '\n') && (c != EOF))
    ;
}


